﻿using System;
using System.Collections.Generic;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;

namespace Chimp.Core
{
    public class UITextArea : ChimpWidget
    {
        private readonly List<string> mText = new List<string>();
        private Key CurKey;
        private int CurXL = -1;
        public int EditX, EditY;
        public ChimpTexture2D Frame;
        public bool KeyIn;
        public int LeftX;
        public int NextPress;
        private int NextTick;
        public int PressRate = 150;
        public int TickOn = 1;
        public int TopY;
        public bool UpperIn;

        public UITextArea(float x, float y, float w, float h, ChimpWidget p)
            : base(new Vector2(x, y), new Vector2(w, h), p)
        {
            Text = "";
            TickRate = 300;
            Frame = new ChimpTexture2D("Res/UI/textarea1.png");
            mText.Add("");
            EditX = 0;
            EditY = 0;
        }

        public int TickRate { get; set; }

        public string CurText
        {
            get
            {
                if (EditY >= mText.Count)
                {
                    mText.Add(" ");
                    return " ";
                }
                return mText[EditY];
            }
            set
            {
                if (EditY >= mText.Count)
                {
                    mText.Add(" ");
                    return;
                }
                mText[EditY] = value;
            }
        }

        public override void OnKeyDown(Key key)
        {
            switch (key)
            {
                case Key.ShiftLeft:
                case Key.ShiftRight:
                    //	case OpenTK.Input.Key.LShift:
                    //	case OpenTK.Input.Key.RShift:
                    UpperIn = true;
                    return;
                    break;
            }
            CurKey = key;
            KeyIn = true;
            NextPress = Environment.TickCount + PressRate*2;
            PressKey(CurKey);
        }

        public override void OnKeyUp(Key key)
        {
            switch (key)
            {
                case Key.ShiftLeft:
                case Key.ShiftRight:
                    //	case OpenTK.Input.Key.LShift:
                    //	case OpenTK.Input.Key.RShift:
                    UpperIn = false;
                    return;
                    break;
            }
            KeyIn = false;
        }

        public void PressKey(Key key)
        {
            switch (key)
            {
                case Key.Enter:
                    string nl;
                    if (EditX < CurText.Length)
                    {
                        nl = CurText.Substring(EditX);
                    }
                    else
                    {
                        nl = " ";
                    }
                    if (EditX > 0 && EditX < CurText.Length)
                    {
                        mText[EditY] = CurText.Substring(0, EditX);
                        mText.Insert(EditY + 1, nl);
                        EditY++;
                        EditX = 0;
                        return;
                    }
                    else if (EditX == 0)
                    {
                        if (CurText.Length > 0)
                        {
                        }
                        mText[EditY] = "";
                        mText.Insert(EditY + 1, nl);
                        EditY++;
                        EditX = 0;
                        return;
                    }
                    else
                    {
                        mText.Insert(EditY + 1, " ");
                        EditY++;
                        EditX = 0;
                        return;
                    }


                    //mText.Insert (EditY+1, nl);
                    EditY++;
                    EditX = 0;
                    return;
                    break;
                case Key.Up:
                    if (EditY > 0)
                    {
                        EditY--;
                    }
                    else
                    {
                        if (EditX > 0)
                        {
                            EditX--;
                        }
                    }
                    return;
                    break;
                case Key.Down:
                    if (EditY < mText.Count + 1)
                    {
                        EditY++;
                    }
                    else
                    {
                    }
                    return;
                    break;
                case Key.Left:
                    if (EditX > 0)
                    {
                        EditX--;
                    }
                    else
                    {
                        if (EditY > 0)
                        {
                            EditY--;
                            EditX = CurText.Length;
                        }
                    }
                    return;
                    break;
                case Key.Right:
                    if (EditX < CurText.Length)
                    {
                        EditX++;
                    }
                    else
                    {
                        EditX = 0;
                        if (EditY < mText.Count + 1)
                        {
                            EditY++;
                        }
                    }
                    return;
                    break;
                case Key.BackSpace:

                    if (EditX >= CurText.Length && CurText.Length > 0)
                    {
                        CurText = CurText.Substring(0, CurText.Length - 1);
                        EditX = CurText.Length;
                        break;
                    }

                    if (EditX == 0)
                    {
                        if (EditY > 0)
                        {
                            EditX = mText[EditY - 1].Length;
                            mText[EditY - 1] = mText[EditY - 1] + CurText;
                            mText.RemoveRange(EditY, 1);
                            EditY--;
                            return;
                        }
                    }

                    if (EditX > 0 && CurText.Length > 1)
                    {
                        CurText = CurText.Substring(0, EditX - 1) + CurText.Substring(EditX);
                        EditX -= 1;
                        return;
                    }
                    else if (EditX > 0)
                    {
                        CurText = "";
                        EditX = 0;
                    }
                    return;
                    //			break;
                case Key.Delete:
                    if (EditX >= CurText.Length)
                    {
                        //CurText = CurText.Substring (0, CurText.Length - 1);
                        //EditX = CurText.Length;
                        if (EditY + 1 < mText.Count)
                        {
                            CurText = CurText + mText[EditY + 1];

                            mText.RemoveRange(EditY + 1, 1);
                        }
                        return;
                        break;
                    }

                    if (EditX == 0 && CurText.Length > 1)
                    {
                        CurText = CurText.Substring(1);
                        return;
                        break;
                    }
                    else if (EditX == 0)
                    {
                        CurText = "";
                        EditX = 0;
                        return;
                        break;
                    }

                    if (EditX > 0 && CurText.Length > 1)
                    {
                        CurText = CurText.Substring(0, EditX) + CurText.Substring(EditX + 1);
                        return;
                        break;
                    }
                    else if (EditX > 0)
                    {
                        CurText = "";
                        if (EditY + 1 < mText.Count)
                        {
                            CurText = CurText + mText[EditY + 1];

                            mText.RemoveRange(EditY + 1, 1);
                        }
                    }
                    return;
                    //	break;
            }
            string nk = "";
            switch (key)
            {
                case Key.A:
                    nk = "A";
                    break;
                case Key.B:
                    nk = "B";
                    break;
                case Key.C:
                    nk = "C";
                    break;
                case Key.D:
                    nk = "D";
                    break;
                case Key.E:
                    nk = "E";
                    break;
                case Key.F:
                    nk = "F";
                    break;
                case Key.G:
                    nk = "G";
                    break;
                case Key.H:
                    nk = "H";
                    break;
                case Key.I:
                    nk = "I";
                    break;
                case Key.J:
                    nk = "J";
                    break;
                case Key.K:
                    nk = "K";
                    break;
                case Key.L:
                    nk = "L";
                    break;
                case Key.M:
                    nk = "M";
                    break;
                case Key.N:
                    nk = "N";
                    break;
                case Key.O:
                    nk = "O";
                    break;
                case Key.P:
                    nk = "P";
                    break;
                case Key.Q:
                    nk = "Q";
                    break;
                case Key.R:
                    nk = "R";
                    break;
                case Key.S:
                    nk = "S";
                    break;
                case Key.T:
                    nk = "T";
                    break;
                case Key.U:
                    nk = "U";
                    break;
                case Key.V:
                    nk = "V";
                    break;
                case Key.W:
                    nk = "W";
                    break;
                case Key.X:
                    nk = "X";
                    break;
                case Key.Y:
                    nk = "Y";
                    break;
                case Key.Z:
                    nk = "Z";
                    break;
                case Key.Space:
                    if (EditX ==
                        0)
                    {
                        mText[EditY] = " " + mText[EditY];
                        EditX++;
                        return;
                    }
                    if (EditX >= mText[EditY].Length)
                    {
                        mText[EditY] = mText[EditY] + " ";
                        EditX++;
                        return;
                    }
                    mText[EditY] = mText[EditY].Substring(0, EditX) + " " + mText[EditY].Substring(EditX);
                    EditX++;
                    return;
                    break;
                case Key.Number0:
                    nk = "0";
                    break;
                case Key.Number1:
                    nk = "1";
                    break;
                case Key.Number2:
                    nk = "2";
                    break;
                case Key.Number3:
                    nk = "3";
                    break;
                case Key.Number4:
                    nk = "4";
                    break;
                case Key.Number5:
                    nk = "5";
                    break;
                case Key.Number6:
                    nk = "6";
                    break;
                case Key.Number7:
                    nk = "7";
                    break;
                case Key.Number8:
                    nk = "8";
                    break;
                case Key.Number9:
                    nk = "9";
                    break;
                case Key.Comma:
                    if (UpperIn)
                    {
                        nk = "<";
                    }
                    else
                    {
                        nk = ",";
                    }
                    break;
                case Key.Period:
                    if (UpperIn)
                    {
                        nk = ">";
                    }
                    else
                    {
                        nk = ".";
                    }
                    break;
                case Key.Slash:
                    if (UpperIn)
                    {
                        nk = "/";
                    }
                    else
                    {
                        nk = "?";
                    }
                    break;
            }
            string rk = nk;
            if (UpperIn == false)
                nk = nk.ToLower();
            rk = nk;
            //Console.WriteLine ("Write:" + rk + " Key:" + key.ToString ());
            if (EditX == 0)
            {
                CurText = rk + CurText;
                EditX = 1;
                return;
            }
            if (EditX >= CurText.Length)
            {
                CurText = CurText + rk;
                EditX++;
                return;
            }
            CurText = CurText.Substring(0, EditX) + rk + CurText.Substring(EditX);
            EditX++;
        }

        public override bool OnUpdate(Vector2 pos)
        {
            int t = Environment.TickCount;
            if (t > NextTick)
            {
                NextTick = t + TickRate;

                TickOn = 1 - TickOn;
            }


            if (KeyIn)
            {
                int t2 = Environment.TickCount;
                if (t2 > NextPress)
                {
                    NextPress += PressRate;
                    PressKey(CurKey);
                }
            }
            if (KeyIn)
                return true;
            return false;
        }

        private int GetXL()
        {
            int i = 0;
            int xl = 0;
            while (true)
            {
                string k = "";
                for (int j = 0; j < i; j++)
                {
                    k += "-";
                }

                ChimpDraw.Text(Vector2.Zero, k);

                int aw = ChimpDraw.TextCache[k].Width;

                if (aw >= Size.X - 10)
                {
                    xl = i;
                    break;
                }

                i++;
            }
            return xl;
        }

        public override void OnRender()
        {
            if (CurXL == -1)
            {
                CurXL = GetXL();
            }
            if (EditX > CurText.Length)
            {
                EditX = CurText.Length;
            }

            int tl = ((int) Size.Y - 10)/20;
            if ((EditY - TopY) > tl - 1)
            {
                TopY = EditY - (tl - 1);
            }

            if (EditY < TopY)
            {
                TopY = EditY - 2;
                if (TopY < 0)
                {
                    TopY = 0;
                }
            }
            if (EditX < LeftX)
            {
                LeftX = EditX - 2;
                if (LeftX < 0)
                {
                    LeftX = 0;
                }
            }

            int i = 0;
            int xl = CurXL;

            if (EditX - LeftX > xl - 1)
            {
                LeftX = EditX - (xl - 1);
            }

            //Color = new OpenTK.Graphics.Color4 (0.65f, Color.G, Color.B, Color.A);
            ChimpDraw.BlendMode = ChimpBlend.Alpha;

            ChimpDraw.Image(new Vector4(GlobalPos.X, GlobalPos.Y, Size.X, Size.Y), Frame,
                            new Vector4(Color.R, Color.G, Color.B, GlobalAlpha));
            //	ChimpDraw.Text (GlobalPos + new Vector2 (5, 3), CurText);

            int tx = 8 - (LeftX*15);
            int vx = (int) GlobalPos.X + tx;

            string ss = EditX < CurText.Length ? CurText.Substring(0, EditX) : CurText;
            ss = ss.Replace(" ", "A");

            if (ChimpDraw.TextCache.ContainsKey(ss))
            {
                tx += ChimpDraw.TextCache[ss].Width;
            }
            else
            {
                ChimpText.ChimpTextCache tc = ChimpText.CreateText(ss);
                ChimpDraw.TextCache.Add(ss, tc);
                tx += tc.Width;
            }
            //int tx = 8;
            int ty = 3 + 20*EditY - TopY;
            int my = 0;
            //int vx = GlobalPos.X +tx;
            int vy = (int) GlobalPos.Y + 3;
            GL.Enable(EnableCap.ScissorTest);
            GL.Scissor((int) GlobalPos.X, (int) ChimpApp.H - (int) GlobalPos.Y - (int) Size.Y, (int) Size.X,
                       (int) Size.Y);
            Vector4 oldc = ChimpDraw.TextColor;
            ChimpDraw.TextColor = new Vector4(0, 0, 0, 1);

            for (int vi = TopY; vi < mText.Count; vi++)
            {
                ChimpDraw.Text(new Vector2(vx, vy), mText[vi]);
                vy += 20;
                if (vy >= GlobalPos.Y + Size.Y)
                {
                    break;
                }
            }
            ChimpDraw.TextColor = oldc;
            if (TickOn == 1)
            {
                ChimpDraw.Image(new Vector4(GlobalPos.X + tx, GlobalPos.Y + ty, 3, 19), Frame,
                                new Vector4(1, 0.2f, 0.1f, 0.5f));
            }
            GL.Disable(EnableCap.ScissorTest);
        }
    }
}